﻿namespace Holoville.HOTween.Core
{
    using Holoville.HOTween;
    using System;
    using System.Runtime.InteropServices;
    using UnityEngine;

    internal class Path
    {
        internal bool changed;
        private Vector3[] drawPs;
        private float[] lengthsTable;
        internal Vector3[] path;
        public float pathLength;
        private PathType pathType;
        public float[] timesTable;
        public float[] waypointsLength;

        public Path(PathType p_type, params Vector3[] p_path)
        {
            this.pathType = p_type;
            this.path = new Vector3[p_path.Length];
            Array.Copy(p_path, this.path, this.path.Length);
        }

        private float GetConstPathPercFromTimePerc(float t)
        {
            if ((t > 0f) && (t < 1f))
            {
                float num = this.pathLength * t;
                float num2 = 0f;
                float num3 = 0f;
                float num4 = 0f;
                float num5 = 0f;
                int length = this.lengthsTable.Length;
                for (int i = 0; i < length; i++)
                {
                    if (this.lengthsTable[i] > num)
                    {
                        num4 = this.timesTable[i];
                        num5 = this.lengthsTable[i];
                        if (i > 0)
                        {
                            num3 = this.lengthsTable[i - 1];
                        }
                        break;
                    }
                    num2 = this.timesTable[i];
                }
                t = num2 + (((num - num3) / (num5 - num3)) * (num4 - num2));
            }
            if (t > 1f)
            {
                t = 1f;
                return t;
            }
            if (t < 0f)
            {
                t = 0f;
            }
            return t;
        }

        internal Vector3 GetConstPoint(float t)
        {
            if (this.pathType == PathType.Linear)
            {
                return this.GetPoint(t);
            }
            float constPathPercFromTimePerc = this.GetConstPathPercFromTimePerc(t);
            return this.GetPoint(constPathPercFromTimePerc);
        }

        internal Vector3 GetConstPoint(float t, out float out_pathPerc, out int out_waypointIndex)
        {
            if (this.pathType == PathType.Linear)
            {
                out_pathPerc = t;
                return this.GetPoint(t, out out_waypointIndex);
            }
            float constPathPercFromTimePerc = this.GetConstPathPercFromTimePerc(t);
            out_pathPerc = constPathPercFromTimePerc;
            out_waypointIndex = -1;
            return this.GetPoint(constPathPercFromTimePerc);
        }

        public Vector3 GetPoint(float t)
        {
            int num;
            return this.GetPoint(t, out num);
        }

        internal Vector3 GetPoint(float t, out int out_waypointIndex)
        {
            if (this.pathType != PathType.Linear)
            {
                int num8 = this.path.Length - 3;
                int num9 = (int) Math.Floor((double) (t * num8));
                int num10 = num8 - 1;
                if (num10 > num9)
                {
                    num10 = num9;
                }
                float num11 = (t * num8) - num10;
                Vector3 vector3 = this.path[num10];
                Vector3 vector4 = this.path[num10 + 1];
                Vector3 vector5 = this.path[num10 + 2];
                Vector3 vector6 = this.path[num10 + 3];
                out_waypointIndex = -1;
                return (Vector3) (0.5f * (((((((-vector3 + (3f * vector4)) - (3f * vector5)) + vector6) * ((num11 * num11) * num11)) + (((((2f * vector3) - (5f * vector4)) + (4f * vector5)) - vector6) * (num11 * num11))) + ((-vector3 + vector5) * num11)) + (2f * vector4)));
            }
            if (t <= 0f)
            {
                out_waypointIndex = 1;
                return this.path[1];
            }
            int index = 0;
            int num2 = 0;
            int length = this.timesTable.Length;
            for (int i = 1; i < length; i++)
            {
                if (this.timesTable[i] >= t)
                {
                    index = i - 1;
                    num2 = i;
                    break;
                }
            }
            float num5 = this.timesTable[index];
            float num6 = this.timesTable[num2] - this.timesTable[index];
            num6 = t - num5;
            float maxLength = this.pathLength * num6;
            Vector3 vector = this.path[index];
            Vector3 vector2 = this.path[num2];
            out_waypointIndex = num2;
            return (vector + Vector3.ClampMagnitude(vector2 - vector, maxLength));
        }

        public void GizmoDraw()
        {
            this.GizmoDraw(-1f, false);
        }

        public void GizmoDraw(float t, bool p_drawTrig)
        {
            Vector3 point;
            Vector3 vector2;
            Gizmos.color = new Color(0.6f, 0.6f, 0.6f, 0.6f);
            if (this.changed || ((this.pathType == PathType.Curved) && (this.drawPs == null)))
            {
                this.changed = false;
                if (this.pathType == PathType.Curved)
                {
                    int num = this.path.Length * 10;
                    this.drawPs = new Vector3[num + 1];
                    for (int j = 0; j <= num; j++)
                    {
                        float num3 = ((float) j) / ((float) num);
                        point = this.GetPoint(num3);
                        this.drawPs[j] = point;
                    }
                }
            }
            if (this.pathType == PathType.Linear)
            {
                vector2 = this.path[1];
                int length = this.path.Length;
                for (int k = 1; k < (length - 1); k++)
                {
                    point = this.path[k];
                    Gizmos.DrawLine(point, vector2);
                    vector2 = point;
                }
            }
            else
            {
                vector2 = this.drawPs[0];
                int num6 = this.drawPs.Length;
                for (int m = 1; m < num6; m++)
                {
                    point = this.drawPs[m];
                    Gizmos.DrawLine(point, vector2);
                    vector2 = point;
                }
            }
            Gizmos.color = Color.white;
            int num8 = this.path.Length - 1;
            for (int i = 1; i < num8; i++)
            {
                Gizmos.DrawSphere(this.path[i], 0.1f);
            }
            if (p_drawTrig && (t != -1f))
            {
                Vector3 vector4;
                Vector3 vector6;
                Vector3 from = this.GetPoint(t);
                Vector3 vector5 = from;
                float num10 = t + 0.0001f;
                if (num10 > 1f)
                {
                    vector6 = from;
                    vector5 = this.GetPoint(t - 0.0001f);
                    vector4 = this.GetPoint(t - 0.0002f);
                }
                else
                {
                    float num11 = t - 0.0001f;
                    if (num11 < 0f)
                    {
                        vector4 = from;
                        vector5 = this.GetPoint(t + 0.0001f);
                        vector6 = this.GetPoint(t + 0.0002f);
                    }
                    else
                    {
                        vector4 = this.GetPoint(num11);
                        vector6 = this.GetPoint(num10);
                    }
                }
                Vector3 lhs = vector6 - vector5;
                lhs.Normalize();
                Vector3 rhs = vector5 - vector4;
                rhs.Normalize();
                Vector3 vector9 = Vector3.Cross(lhs, rhs);
                vector9.Normalize();
                Vector3 vector10 = Vector3.Cross(lhs, vector9);
                vector10.Normalize();
                Gizmos.color = Color.black;
                Gizmos.DrawLine(from, from + lhs);
                Gizmos.color = Color.blue;
                Gizmos.DrawLine(from, from + vector9);
                Gizmos.color = Color.red;
                Gizmos.DrawLine(from, from + vector10);
            }
        }

        internal void StoreTimeToLenTables(int p_subdivisions)
        {
            Vector3 point;
            Vector3 vector2;
            if (this.pathType == PathType.Linear)
            {
                this.pathLength = 0f;
                int length = this.path.Length;
                this.waypointsLength = new float[length];
                point = this.path[1];
                for (int i = 1; i < length; i++)
                {
                    vector2 = this.path[i];
                    float num4 = Vector3.Distance(vector2, point);
                    if (i < (length - 1))
                    {
                        this.pathLength += num4;
                    }
                    point = vector2;
                    this.waypointsLength[i] = num4;
                }
                this.timesTable = new float[length];
                float num5 = 0f;
                for (int j = 2; j < length; j++)
                {
                    num5 += this.waypointsLength[j];
                    this.timesTable[j] = num5 / this.pathLength;
                }
            }
            else
            {
                this.pathLength = 0f;
                float num = 1f / ((float) p_subdivisions);
                this.timesTable = new float[p_subdivisions];
                this.lengthsTable = new float[p_subdivisions];
                point = this.GetPoint(0f);
                for (int k = 1; k < (p_subdivisions + 1); k++)
                {
                    float t = num * k;
                    vector2 = this.GetPoint(t);
                    this.pathLength += Vector3.Distance(vector2, point);
                    point = vector2;
                    this.timesTable[k - 1] = t;
                    this.lengthsTable[k - 1] = this.pathLength;
                }
            }
        }

        internal void StoreWaypointsLengths(int p_subdivisions)
        {
            int num = this.path.Length - 2;
            this.waypointsLength = new float[num];
            this.waypointsLength[0] = 0f;
            Path path = null;
            for (int i = 2; i < (num + 1); i++)
            {
                Vector3[] vectorArray = new Vector3[] { this.path[i - 2], this.path[i - 1], this.path[i], this.path[i + 1] };
                if (i == 2)
                {
                    path = new Path(this.pathType, vectorArray);
                }
                else
                {
                    path.path = vectorArray;
                }
                float num3 = 0f;
                float num4 = 1f / ((float) p_subdivisions);
                Vector3 point = path.GetPoint(0f);
                for (int j = 1; j < (p_subdivisions + 1); j++)
                {
                    float t = num4 * j;
                    Vector3 a = path.GetPoint(t);
                    num3 += Vector3.Distance(a, point);
                    point = a;
                }
                this.waypointsLength[i - 1] = num3;
            }
        }

        public Vector3 Velocity(float t)
        {
            int num = this.path.Length - 3;
            int num2 = (int) Math.Floor((double) (t * num));
            int index = num - 1;
            if (index > num2)
            {
                index = num2;
            }
            float num4 = (t * num) - index;
            Vector3 vector = this.path[index];
            Vector3 vector2 = this.path[index + 1];
            Vector3 vector3 = this.path[index + 2];
            Vector3 vector4 = this.path[index + 3];
            return (Vector3) (((((1.5f * (((-vector + (3f * vector2)) - (3f * vector3)) + vector4)) * (num4 * num4)) + (((((2f * vector) - (5f * vector2)) + (4f * vector3)) - vector4) * num4)) + (0.5f * vector3)) - (0.5f * vector));
        }
    }
}

